import { watch, ref, computed } from 'vue';
import type { Ref } from 'vue';
import { useSiweMessage, useSiweMessageValidator } from '/@/hooks/useSiweMessage';
import { getNonce } from '/@/api/user';
import {
  useSignMessage,
  useAccount,
  useConnect,
  RpcError,
  useNetwork,
  useSwitchNetwork,
  chain,
} from 'vagmi';
import { InjectedConnector } from 'vagmi/connectors/injected';
import { Message } from '@arco-design/web-vue';

interface UseWalletSignatureParams {
  address: Ref<string | undefined>;
}
export function useWalletSignature(params: UseWalletSignatureParams) {
  const { address: addressRef } = params;
  const { isConnected } = useConnect();
  const { data: signMessageResultRef, isSuccess, signMessageAsync, error } = useSignMessage();
  const messageRef = ref('');
  const isLoadingRef = ref(false);
  const signatureRef = ref('');
  const isSuccessRef = ref(false);

  watch(signMessageResultRef, (signMessageResult) => {
    signatureRef.value = signMessageResult || '';
  });

  watch(isSuccess, (isSuccess) => {
    isSuccessRef.value = isSuccess;
  });

  watch(isConnected, (isConnected) => {
    if (!isConnected) {
      messageRef.value = '';
      signatureRef.value = '';
      isSuccessRef.value = false;
    }
  });

  watch(error, (err) => {
    if (err) {
      Message.error(err.message);
    }
  });

  async function execute() {
    const address = addressRef.value;
    if (address) {
      try {
        isLoadingRef.value = true;
        const data = await getNonce({ address });
        const { nonce } = data;
        const { message } = useSiweMessage({
          address,
          statement: 'Sign in to the Polestar.',
          nonce,
        });
        messageRef.value = message.value;
        await signMessageAsync({ message: message.value });
        if (import.meta.env.DEV) {
          const { isValid, execute: validate } = useSiweMessageValidator({
            message: messageRef,
            nonce: ref(nonce),
            signature: signatureRef,
          });
          await validate();
          console.log('前端校验签名结果：', isValid.value);
        }
      } finally {
        isLoadingRef.value = false;
      }
    }
  }

  return {
    message: messageRef,
    signature: signatureRef,
    execute,
    isLoading: isLoadingRef,
    isSuccess: isSuccessRef,
  };
}

export function useWalletConnect() {
  const { address: addressRef } = useAccount();
  const { chains, isLoading, switchNetworkAsync } = useSwitchNetwork();
  const { chain: chainRef } = useNetwork();
  const { connectAsync, isConnected, isConnecting } = useConnect({
    connector: new InjectedConnector({
      chains: [import.meta.env.PROD ? chain.polygon : chain.polygonMumbai],
    }),
  });

  async function execute() {
    // 连接钱包
    if (!isConnected.value) {
      try {
        await connectAsync.value();
      } catch (error) {
        if ((error as RpcError).code) {
          Message.error((error as RpcError).message);
          throw error;
        }
      }
    }

    // 切换链
    if (chains.value[0]?.id !== chainRef?.value?.id) {
      try {
        await switchNetworkAsync.value?.(chains.value[0]?.id);
      } catch (error) {
        if ((error as RpcError).code) {
          Message.error((error as RpcError).message);
          throw error;
        }
      }
    }
  }

  return {
    data: addressRef,
    execute,
    isLoading: computed(() => isConnecting.value || isLoading.value),
  };
}
